package mlp;
import java.util.ArrayList;
import java.util.Random;

import function.SigmoidalFunction;

public class MlpPso extends pso.Function {

	public MLP mlp;
	public Data data;
	private ArrayList<Element> elementosTemporario;

	public MlpPso(String path){
		initialize(path);
	}

	public void initialize(String path){
		int entradas = 7;
		int camadaEscondida1 = 6;
		int camadaEscondida2 = 5;
		int saidas = 1;
//		int[] vetor = {entradas,camadaEscondida1,camadaEscondida2,saidas};
		int[] vetor = {entradas,camadaEscondida1,saidas};
		
		//pesos igual escondida * (entrada+1) + saida *(esc + 1)
				int totalPesos = camadaEscondida1 * (entradas + 1) + saidas * (camadaEscondida1+1);
//		int totalPesos = camadaEscondida1 * (entradas + 1) + camadaEscondida2 * (camadaEscondida1+1) 
//		+ saidas * (camadaEscondida2+1);
		numDimensions = totalPesos;
		this.mlp = new MLP(vetor, new SigmoidalFunction(), 1);		
		this.data = new Data(path);
		this.elementosTemporario = (ArrayList<Element>) this.data.elementos.clone();		
	}


	public double runMLP(){
		Random random = new Random();
		//copia a lista de todos os elementos
		this.elementosTemporario = (ArrayList<Element>) this.data.elementos.clone();		
		double erro = 0;
		Element elemento;
		while (this.elementosTemporario.size() != 0){	
			//remove um elemento aleatorio
			elemento = elementosTemporario.remove(random.nextInt(elementosTemporario.size()));		
			//dados de entrada
			double[] input = elemento.getInput();
			//classe relativa a esse elemento
			double classe = elemento.getClasse();
			double[] classeEsperada  = {classe};
			//saida calculada da rede
			double[] classeSaida = this.mlp.calculateOutput(input, true);
			//			System.out.println(classeSaida[0] + " " + classe) ;
			//calculo do erro
			//erro += this.mlp.calcularErro(classeSaida, classeEsperada);
			erro += this.mlp.calcularErroPercentual(classeSaida, classeEsperada);

		}
		return - erro/(double)this.data.elementos.size();
		//		return erro/(double)2;

	}
	public double emq() {
		Random random = new Random();
		this.elementosTemporario = (ArrayList<Element>) this.data.elementos.clone();		
		double erro = 0;
		Element elemento;
		while (this.elementosTemporario.size() != 0){
			//remove um elemento aleatorio
			elemento = elementosTemporario.remove(random.nextInt(elementosTemporario.size()));		
			//dados de entrada
			double[] input = elemento.getInput();
			//classe relativa a esse elemento
			double classe = elemento.getClasse();
			double[] classeEsperada  = {classe};
			//saida calculada da rede
			double[] classeSaida = this.mlp.calculateOutput(input, true);
			//			System.out.println(classeSaida[0] + " " + classe) ;
			//calculo do erro
			erro += this.mlp.calcularErro(classeSaida, classeEsperada);

		}
		return (erro/(double)this.data.elementos.size());

	}


	@Override
	public double calculate(double[] x) {
		this.mlp.changeWeigths(x);
		double erro = runMLP();
		return erro;
	}

	@Override
	public double getMinBoudaries() {
		// TODO Auto-generated method stub
		return -10;
	}

	@Override
	public double getMaxBoudaries() {
		// TODO Auto-generated method stub
		return 10;
	}

}
